//Namespace
var squigle = {};

//Get the global adaptor
squigle.getAdapter = function(){
    return squigle._adaptor;
};

/**
 * VML does not allow floats but does except 2^16 string representations of floats (binary scaling)
 * If you will be working with numbers less than six digits in length then set this to true (default)
 * If you are working with large numbers set this to false, but be aware that all floats will be rounded to the nearest whole number
 */
squigle.preserveDecimals = false;

//Set the global adaptor
squigle.setAdapter = function(adaptor, preserveDecimals){
    squigle._adaptor = adaptor;
    if(typeof preserveDecimals == 'boolean'){
        squigle.preserveDecimals = preserveDecimals;      
    }
    
    //Set Point and Size
    squigle.Point = adaptor.Point;
    squigle.Size = adaptor.Size;
};

/**
 * Entities
 */
squigle.Canvas = function(size, coordSize, coordOrigin){
    coordSize = coordSize || size;
    coordOrigin = coordOrigin || new squigle.Point();
    var _adaptor =  squigle.getAdapter();
    var _canvas = this._canvasDependancy || new _adaptor.Canvas(size, coordSize, coordOrigin);
    var _node = _canvas.node();
    var _container = _canvas.container();

    this.append = function(shape){
        _canvas.append(shape);
        return shape.node();  
    };
    
    this.remove = function(shape){
        return _canvas.node().removeChild(shape.node());
    };
    
    this.node = function(){
        return _node;
    };
    
    this.container = function(){
        return _container;
    };
    
    this.preserveDecimals = function(){
        return _preserveDecimals;
    };    
};
squigle.Canvas.prototype = {
    //Dependancy injection for testing
    _canvasDependancy: null
};


squigle.Rectangle = function(size, point, stroke, fill){
    var _adaptor =  squigle.getAdapter();
    var _rectangle = this._rectangleDependancy || new _adaptor.Rectangle(size, point, stroke, fill);

    this.node = function(){
        return _rectangle.node();
    };
    
    this.stroke = function(){
        return _rectangle.stroke();  
    };
    
    this.scale = function(resolution, retainCenterPoint){
        _adaptor.scale(_rectangle.node(), resolution, retainCenterPoint);
    };     
};
squigle.Rectangle.prototype = {
    //Dependancy injection for testing
    _rectangleDependancy: null  
};

squigle.Path = function(stroke, fill){
    var _adaptor =  squigle.getAdapter();
    var _path = this._pathDependancy || new _adaptor.Path(stroke, fill);

    this.node = function(){
        return _path.node();
    };
    
    this.stroke = function(){
        return _path.stroke();  
    };
    
    this.scale = function(resolution, retainCenterPoint){
        _adaptor.scale(_path.node(), resolution, retainCenterPoint);
    };       
    
    this.moveTo = function(point, relative){
        _path.moveTo(point, relative);
        return this;  
    };
    
    this.lineTo = function(point, relative){
        _path.lineTo(point, relative);
        return this;        
    };
    
    this.curveTo = function(controlPoint1, controlPoint2, endPoint, relative){
        _path.curveTo(controlPoint1, controlPoint2, endPoint, relative);
        return this;         
    };
    
    /**
     * Hat Tip to www.RaphaelJS.com for this code!
     */
    this.roundTo = function(r, dir){
        var R = .5522 * r;
        var o = _path;
        var actions = {
            l: function () {
                return {
                    u: function () {
                        o.curveTo(new squigle.Point(-R, 0), new squigle.Point(-r, -(r - R)), new squigle.Point(-r, -r), true);
                    },
                    d: function () {
                        o.curveTo(new squigle.Point(-R, 0), new squigle.Point(-r, r - R), new squigle.Point(-r, r), true);
                    }
                };
            },
            r: function () {
                return {
                    u: function () {
                        o.curveTo(new squigle.Point(R, 0), new squigle.Point(r, -(r - R)), new squigle.Point(r, -r), true);
                    },
                    d: function () {
                        o.curveTo(new squigle.Point(R, 0), new squigle.Point(r, r - R), new squigle.Point(r, r), true);
                    }
                };
            },
            u: function () {
                return {
                    r: function () {
                        o.curveTo(new squigle.Point(0, -R), new squigle.Point(-(R - r), -r), new squigle.Point(r, -r), true);
                    },
                    l: function () {
                        o.curveTo(new squigle.Point(0, -R), new squigle.Point(R - r, -r), new squigle.Point(-r, -r), true);
                    }
                };
            },
            d: function () {
                return {
                    r: function () {
                        o.curveTo(new squigle.Point(0, R), new squigle.Point(-(R - r), r), new squigle.Point(r, r), true);
                    },
                    l: function () {
                        o.curveTo(new squigle.Point(0, R), new squigle.Point(R - r, r), new squigle.Point(-r, r), true);
                    }
                };
            }
        };
        actions[dir.charAt(0)]()[dir.charAt(1)]();
        return this;           
    };
    
    this.close = function(){
        _path.close();
        return this;      
    };
    
    this.clear = function(){};
};
squigle.Path.prototype = {
    //Dependancy injection for testing
    _pathDependancy: null  
};

/**
 * Value Objects
 */
squigle.Fill = function(color, opacity){
    this.color = function(){
        return color || "#FFFFFF";
    };
    
    this.opacity = function(){
        if(typeof opacity == "number"){
            return opacity;
        }
        return 100;
    };
};

squigle.Stroke = function(color, opacity, size, endcap, linejoin, dash){
    this.color = function(){
        return color || "#000000";
    };
    
    this.opacity = function(){
        if(typeof opacity == "number"){
            return opacity;
        }
        return 100;
    };
    
    this.size = function(){
        return size || 1;
    };
    
    this.endcap = function(){
        return endcap || "round";
    };
    
    this.linejoin = function(){
        return linejoin || "round";
    };
    
    this.dash = function(){
        return dash || "solid";
    };    
};